using System;
using System.Collections.Generic;
using System.Runtime.CompilerServices;
using br.odb.liboldfart.wavefront_obj;
using Gtk;
//-----------------------------------------------------------------------------
namespace MonoBED3
{
//-----------------------------------------------------------------------------
	[System.ComponentModel.ToolboxItem(true)]
	public partial class PaletteWidget : Gtk.Bin, ContextAware, ContextListener
	{
		//hack
		//static int currentFace;
//-----------------------------------------------------------------------------		
		public void setContext(EditorContext instance)
		{
			//editor = instance;	
			this.updateWidgets();
		}
//-----------------------------------------------------------------------------		
		public EditorContext getContext()
		{
			return MainWindow.editContext;	
		}
//-----------------------------------------------------------------------------		
		public PaletteWidget ()
		{
			this.Build ();
		}
//-----------------------------------------------------------------------------				
		protected virtual void OnBtnCreateEntityClicked (object sender, System.EventArgs e)
		{
			EntityKind kind = (EntityKind) this.cboEntityKindCreate.Active;
			
			if ( getContext() != null)
				getContext().addNewEntity(kind);
			else
				Logger.log("**ERROR** No editor context available.");
			
		}	
		
		protected virtual void OnLblDuplicateEntityClicked (object sender, System.EventArgs e) {
			Logger.log("duplicate entity");
		}
		
		protected virtual void OnBtnDeleteEntityClicked (object sender, System.EventArgs e) {
			deleteCurrentEntity();
		}
		
		[MethodImpl(MethodImplOptions.Synchronized)]
		public void deleteCurrentEntity() {
			
			if ( getContext() != null && getContext().getCurrentEntityFacade() != null ) {
				getContext().lockContext();
				Sector sector = ( ( Sector ) getContext().getCurrentEntityFacade().getObject() );
				getContext().removeEntity( sector );
				getContext().setCurrentSectorId( 0 );
				getContext().unlockContext();
				getContext().notifyChange();
			}
		}
		
		protected virtual void OnBtnDeleteFaceLinkClicked (object sender, System.EventArgs e) {
	
			int face = this.cmbSelectFace.Active; //currentFace;
			if ( getContext() != null && getContext().getCurrentEntityFacade() != null ) {
				
				( ( Sector ) getContext().getCurrentEntityFacade().getObject() ).setLink( face, 0 );
				getContext().notifyChange();
			}
		}
		
		
		protected virtual void OnBtnAddLampActorClicked (object sender, System.EventArgs e) {
			Console.WriteLine("add lamp actor");
		}
		
		protected virtual void OnFaceColorBtnColorSet (object sender, System.EventArgs e)
		{
			Sector s = ( ( Sector ) getContext().getCurrentEntityFacade().getObject() );
			Color c = new Color();
			c.setR( ((float)FaceColorBtn.Color.Red) / ((float)ushort.MaxValue) );
			c.setG( ((float)FaceColorBtn.Color.Green) / ((float)ushort.MaxValue) );
			c.setB( ((float)FaceColorBtn.Color.Blue) / ((float)ushort.MaxValue) );	
		
			s.setColor( this.cmbSelectFace.Active, c );
			getContext().askForScreenRefresh();
		}
		
		protected virtual void OnCboEntitiesChanged (object sender, System.EventArgs e)
		{
			if ( getContext().getTotalSectors() > 0 && cboEntities.Active >= 0 && cboEntities.Active < getContext().getTotalSectors() ) {
				getContext().setCurrentSectorId( cboEntities.Active );	
			}
		}
		


		
		private void updateCombo() {
			
	        CellRendererText cell;
			ListStore store;
			
			cboEntities.Clear();
			cboLink.Clear();
			cell = new CellRendererText();
	        cboEntities.PackStart(cell, false );
	        cboEntities.AddAttribute(cell, "text", 0);
	        store = new ListStore(typeof (string));
			cboEntities.Model = store;
			
			cell = new CellRendererText();
	        cboLink.PackStart(cell, false );
	        cboLink.AddAttribute(cell, "text", 0);
			cboLink.Model = store;
			
			store.AppendValues ("-" );
			
			if ( getContext() != null ) {

				for ( int c = 1; c < getContext().getTotalSectors(); ++c ) {

		       		store.AppendValues ("Sector " + c );
				}
			}
			
			if ( getContext() != null && getContext().getCurrentEntityFacade() != null )
				cboEntities.Active = getContext().getCurrentEntityFacade().getId();
		}
		
	
		private byte clamp( byte x, byte min, byte max ) {
			
			if ( x < min )
				return min;
			
			if ( x > max )
				return max;
			
			return x;
		}
		
		[MethodImpl(MethodImplOptions.Synchronized)]
		private void updateWidgets() {
			
			int currentFace = this.cmbSelectFace.Active;
			updateCombo();
			
			if ( getContext() == null ) {
				chkIsSolid.Active = false;
				chkIsDoor.Active = false;
				chkIsSolid.Sensitive = false;
				chkIsDoor.Sensitive = false;
				return;
			}
			
			spnCursorX.Value = getContext().getCursor().getX();
			spnCursorY.Value = getContext().getCursor().getY();
			spnCursorZ.Value = getContext().getCursor().getZ();
			
			if ( getContext() != null && getContext().getCurrentSectorId() > 0 ) {
				int id = getContext().getCurrentSectorId();
				SectorFacade f = getContext().getSectorFacade( id );
				Sector s = f.getObject() as Sector;
				cboLink.Active = s.getLink( currentFace );
				
				//aqui entra atualização de widgets para um dado sector
				
				Color color = s.getColor( currentFace );
				byte r = clamp( ( byte )( color.getR() ), 0, 255 );
				byte g = clamp( ( byte )( color.getG() ), 0, 255 );
				byte b = clamp( ( byte )( color.getB() ), 0, 255 );
				FaceColorBtn.Color = new Gdk.Color( r,g,b );
				
				if ( s.getLink( currentFace ) != 0 ) {
					
					chkIsDoor.Active = s.IsDoorAt( currentFace );
					chkIsDoor.State = StateType.Active;					
				} else {
					chkIsDoor.Active = false;
					chkIsDoor.State = StateType.Insensitive;
				}
				
				this.decalFileChooser.SetFilename( s.getDecal( currentFace ) );
				spnFloorHeight.Value = s.getY0();
				spnCeilingHeight.Value = s.getY1();
				cboLink.Active = s.getLink( currentFace );
			}
			
			if ( getContext().getCurrentSectorId() != -1 ) {
			
				cboEntities.Active = getContext().getCurrentSectorId();
			}
			
			if ( getContext().getCurrentEntityFacade() != null ) {
				
				chkIsSolid.Sensitive = true;
				
				chkIsDoor.Sensitive = true;				
				chkIsSolid.Active = ( ( GameObject ) getContext().getCurrentEntityFacade().getObject() ).isSolid();
				
				if ( getContext().getCurrentEntityFacade().getObject() is Sector ) {
					chkIsDoor.Active = ( ( Sector ) getContext().getCurrentEntityFacade().getObject() ).IsDoorAt( currentFace );
				}						
				
			} else {
				chkIsSolid.Active = false;
				chkIsDoor.Active = false;
				chkIsSolid.Sensitive = false;
				chkIsDoor.Sensitive = false;
				
			}
		}
		protected virtual void OnChkIsSolidToggled (object sender, System.EventArgs e)
		{
			if ( getContext().getCurrentEntityFacade().getObject() is GameObject )			
				( ( GameObject ) getContext().getCurrentEntityFacade().getObject() ).setSolidState( chkIsSolid.Active  );
			updateWidgets();
		}
		
		protected virtual void OnChkIsDoorToggled (object sender, System.EventArgs e) {
		
			int currentFace = this.cmbSelectFace.Active;
			if ( ( getContext().getCurrentEntityFacade().getObject() is Sector ) ) {
				
				( ( Sector ) getContext().getCurrentEntityFacade().getObject() ).setIsDoor( currentFace, chkIsDoor.Active, ( ( Sector ) getContext().getCurrentEntityFacade().getObject() ).getLink( currentFace ) );
			}
		}
		
		public void contextModified() {
			updateWidgets();
		}
		
		protected virtual void OnCboLinkChanged (object sender, System.EventArgs e) {
			
			int face = this.cmbSelectFace.Active;
			
			if ( getContext() != null && getContext().getCurrentEntityFacade() != null ) {
				
				( ( Sector ) getContext().getCurrentEntityFacade().getObject() ).setLink( face, cboLink.Active );
				getContext().notifyChange();
			}
		}
		
		protected virtual void OnCmbSelectFaceChanged (object sender, System.EventArgs e)
		{
			updateWidgets();
		}
		
		protected virtual void OnBtnExportSectorMeshActivated (object sender, System.EventArgs e)
		{
			exportCurrentSector();
		}
		
		private void exportCurrentSector() {
			
			Gtk.FileChooserDialog fc = new Gtk.FileChooserDialog( "Please name file to export sector mesh",
			                                                      MainWindow.getInstance(),
			                                                      FileChooserAction.Save,
			                                                      "Cancel",
			                                                      ResponseType.Cancel,
			                                                      "Export",
			                                                      ResponseType.Accept );	 	
	
	        if ( fc.Run() == ( int )ResponseType.Accept ) {
				
				
				if ( getContext().getCurrentEntityFacade().getObject() is Sector ) {

		       		getContext().exportSectorAsObjTo( getContext().getCurrentEntityFacade().getObject() as Sector, fc.Filename.ToString() );
				}
			}	
			
			fc.Destroy();
		}
		
		protected virtual void OnBtnExportSectorMeshClicked (object sender, System.EventArgs e)
		{
			exportCurrentSector();
		}
//-----------------------------------------------------------------------------		

		protected void OnCmbEditModeChanged (object sender, System.EventArgs e)
		{
			MainWindow.altButtonBehaviour = cmbEditMode.Active;
		}

		protected void OnChkIsDoorClicked (object sender, System.EventArgs e)
		{


		}

		protected void OnSpnCeilingHeightChangeValue (object o, Gtk.ChangeValueArgs args)
		{

		}

		protected void OnSpnFloorHeightChangeValue (object o, Gtk.ChangeValueArgs args)
		{
		}
		
		protected virtual void OnLblRemoveDecalClicked (object sender, System.EventArgs e) {
				
			int id = getContext().getCurrentSectorId();
			//Console.WriteLine( "id = " + id );
			SectorFacade f = getContext().getSectorFacade( id );
			//Console.WriteLine( "f = " + f );
			Sector s = f.getObject() as Sector;
			
			s.setDecal( cmbSelectFace.Active, null );
			getContext().askForScreenRefresh();
		}	
		
		protected void OnFilechooserbutton1SelectionChanged (object sender, System.EventArgs e)
		{
			
			int id = getContext().getCurrentSectorId();
			//Console.WriteLine( "id = " + id );
			SectorFacade f = getContext().getSectorFacade( id );
			//Console.WriteLine( "f = " + f );
			Sector s = f.getObject() as Sector;
			String decalUri = decalFileChooser.Filename;
			s.setDecal( cmbSelectFace.Active, decalUri );
			getContext().askForScreenRefresh();			
		}

		protected void OnSpnCeilingHeightValueChanged (object sender, System.EventArgs e)
		{
				int id = getContext().getCurrentSectorId();
				//Console.WriteLine( "id = " + id );
				SectorFacade f = getContext().getSectorFacade( id );
				Sector s = f.getObject() as Sector;
				s.setY1( (float)this.spnCeilingHeight.Value );
				getContext().askForScreenRefresh();
		}

		protected void OnSpnFloorHeightValueChanged (object sender, System.EventArgs e)
		{
				int id = getContext().getCurrentSectorId();
				//Console.WriteLine( "id = " + id );
				SectorFacade f = getContext().getSectorFacade( id );
				//Console.WriteLine( "f = " + f );
				Sector s = f.getObject() as Sector;
				s.setY0( (float)this.spnFloorHeight.Value );
				getContext().askForScreenRefresh();

		}
		

		void reset() {

		}
		
		void setDrawGrid( bool shouldDrawGrid ) {

		}		

		protected void OnEntCursorXEditingDone (object sender, System.EventArgs e)
		{
		//	getContext().getCursor().setX( ( float ) System.Convert.ToDouble( entCursorX.Text ) );
			getContext().askForScreenRefresh();
		}

		protected void OnEntCursorYEditingDone (object sender, System.EventArgs e)
		{
//getContext().getCursor().setY( ( float ) System.Convert.ToDouble( entCursorY.Text ) );
			getContext().askForScreenRefresh();
		}

		protected void OnEntCursorZEditingDone (object sender, System.EventArgs e)
		{
		//	getContext().getCursor().setZ( ( float ) System.Convert.ToDouble( entCursorZ.Text ) );
			getContext().askForScreenRefresh();
		}

		protected void OnSpnCursorZChangeValue (object o, Gtk.ChangeValueArgs args)
		{
			throw new System.NotImplementedException ();
		}

		protected void OnSpnCursorZValueChanged (object sender, System.EventArgs e)
		{
			getContext().getCursor().setZ( ( float ) spnCursorZ.Value );
			getContext().askForScreenRefresh();
		}
		

		protected void OnSpnCursorYChangeValue (object o, Gtk.ChangeValueArgs args)
		{
			throw new System.NotImplementedException ();
		}

		protected void OnSpnCursorYValueChanged (object sender, System.EventArgs e)
		{
			getContext().getCursor().setY( ( float ) spnCursorY.Value );
			getContext().askForScreenRefresh();
		}

		protected void OnSpnCursorXChangeValue (object o, Gtk.ChangeValueArgs args)
		{
			throw new System.NotImplementedException ();
		}

		protected void OnSpnCursorXValueChanged (object sender, System.EventArgs e)
		{
			getContext().getCursor().setX( ( float ) spnCursorX.Value );
			getContext().askForScreenRefresh();
		}
	}
//-----------------------------------------------------------------------------	
}

